package com.tgy.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.tgy.ao.CommentAo;
import com.tgy.blog.service.DeskArticleService;
import com.tgy.constant.Constant;
import com.tgy.constant.RedisKey;
import com.tgy.core.service.BlogArticleService;
import com.tgy.core.service.BlogCategoryService;
import com.tgy.core.service.BlogCommentService;
import com.tgy.core.service.BlogUserService;
import com.tgy.enums.ArticleReviewLevel;
import com.tgy.enums.YesOrNo;
import com.tgy.jwt.JWTUtils;
import com.tgy.page.PageQuery;
import com.tgy.page.TableDataInfo;
import com.tgy.pojo.BlogArticle;
import com.tgy.pojo.BlogCategory;
import com.tgy.pojo.BlogComment;
import com.tgy.pojo.BlogUser;
import com.tgy.result.GraceJSONResult;
import com.tgy.result.ResultObj;
import com.tgy.util.IPUtils;
import com.tgy.util.RedisUtils;
import com.tgy.util.WebUtils;
import com.tgy.util.aliyun.AliTextReviewUtils;
import com.tgy.vo.CommentVo;
import com.tgy.vo.GitCommitHistoryVo;
import com.tgy.vo.RecentlyCommentVo;
import com.tgy.vo.TimeLineVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tianguiyin
 * @version 1.0
 * @date 2022/7/9 19:02
 */
@Service
public class DeskArticleServiceImpl implements DeskArticleService {

    @Resource
    private BlogArticleService blogArticleService;
    @Resource
    private BlogCategoryService blogCategoryService;
    @Resource
    private BlogUserService blogUserService;
    @Resource
    private BlogCommentService blogCommentService;
    @Resource
    private AliTextReviewUtils aliTextReviewUtils;
    @Resource
    private RedisUtils redis;


    @Override
    public TableDataInfo<BlogArticle> getIndexArticleList(PageQuery pageQuery) {
        // pageQuery.setLimit(5);
        pageQuery.setOrderByColumn("top,createdTime");
        pageQuery.setIsAsc("desc");
        BlogArticle article = new BlogArticle();
        article.setStatus(YesOrNo.YES.type);
        return blogArticleService.queryPageList(article, pageQuery);
    }

    @Override
    public List<BlogArticle> getRankingArticleList(PageQuery pageQuery) {
        if (pageQuery.getLimit()>10){
            pageQuery.setLimit(10);
        }
        // 根据浏览量倒叙查询
        pageQuery.setOrderByColumn("watchNumber,createdTime");
        pageQuery.setIsAsc("desc");
        // 永远只查第一页
        pageQuery.setPage(1);

        BlogArticle article = new BlogArticle();
        ArrayList<String> existFields = new ArrayList<>();
        existFields.add("content");
        article.setExistFields(existFields);
        article.setStatus(YesOrNo.YES.type);
        TableDataInfo<BlogArticle> dataInfo = blogArticleService.queryPageList(article, pageQuery);
        return dataInfo.getRows();
    }

    @Override
    public List<BlogArticle> getRecommendedArticleList(PageQuery pageQuery) {
        if (pageQuery.getLimit()>10){
            pageQuery.setLimit(10);
        }
        // 原创的，时间倒叙
        BlogArticle bo = new BlogArticle();
        bo.setOriginal(YesOrNo.YES.type);
        bo.setStatus(YesOrNo.YES.type);
        // 永远只查第一页
        pageQuery.setPage(1);

        ArrayList<String> existFields = new ArrayList<>();
        existFields.add("content");
        bo.setExistFields(existFields);
        TableDataInfo<BlogArticle> dataInfo = blogArticleService.queryPageList(bo, pageQuery);
        return dataInfo.getRows();
    }

    @Override
    public List<BlogCategory> getCategory() {
        return blogCategoryService.queryList(new BlogCategory());
    }

    @Override
    public List<BlogArticle> getSimilarArticleList(String categoryIds,PageQuery pageQuery) {
        BlogArticle article = new BlogArticle();
        article.setCategoryId(categoryIds);

        if (pageQuery.getLimit()>10){
            pageQuery.setLimit(10);
        }
        // 根据浏览量倒叙查询
        pageQuery.setOrderByColumn("watchNumber,createdTime");
        pageQuery.setIsAsc("desc");
        // 永远只查第一页
        pageQuery.setPage(1);

        article.setStatus(YesOrNo.YES.type);
        ArrayList<String> existFields = new ArrayList<>();
        existFields.add("content");
        article.setExistFields(existFields);
        TableDataInfo<BlogArticle> dataInfo = blogArticleService.queryPageList(article, pageQuery);
        return dataInfo.getRows();
    }

    @Override
    public TableDataInfo<BlogArticle> getArticleArticleList(BlogArticle bo,PageQuery pageQuery) {
        bo.setStatus(YesOrNo.YES.type);
        return blogArticleService.queryPageList(bo, pageQuery);
    }

    @Override
    public GraceJSONResult addArticleWatch(String articleId) {
        HttpServletRequest request = WebUtils.getRequest();
        String userIp = IPUtils.getRequestIp(request);
        userIp = userIp.replaceAll(":",".");
        //观看数量加1
        // redis.increment(RedisKey.REDIS_ARTICLE_WATCH + ":" + articleId ,1);
        blogArticleService.addWatchNumber(articleId);
        //观看的ip进行存储，防止刷观看数量
        long outTime = 86400L;
        redis.set(RedisKey.REDIS_ARTICLE_USER_WATCH + ":" + articleId +":" + userIp,userIp, outTime);
        return GraceJSONResult.ok();
    }

    @Override
    public GraceJSONResult addComment(CommentAo ao) {
        // 验证token
        ResultObj obj = JWTUtils.verify(ao.getUserToken());
        if (Constant.ERROR.equals(obj.getCode())){
            return GraceJSONResult.error("请重新登录");
        }
        // 内容检测
        String s = aliTextReviewUtils.reviewTextContent(ao.getContent());
        int status = 0;
        if (ArticleReviewLevel.PASS.type.equals(s)){
            status = 1;
        }else if (ArticleReviewLevel.BLOCK.type.equals(s)){
            return GraceJSONResult.error("请使用文明语言评论");
        }

        BlogComment blogComment = new BlogComment();
        blogComment.setStatus(status);
        blogComment.setContent(ao.getContent());

        LocalDateTime now = LocalDateTime.now();
        BlogUser user = blogUserService.queryById(ao.getUserId());
        String userName = user.getNickname();
        blogComment.setUserId(ao.getUserId());
        blogComment.setUserName(userName);
        blogComment.setSite(user.getLatelyLoginAddress());
        blogComment.setCommentDate(now);

        String articleId = ao.getArticle();
        String articleName;
        BlogComment comment = null;
        // 留言或者评论
        if (StrUtil.isNotBlank(articleId)){
            // 留言
            if ("-1".equals(articleId)){
                articleName = "留言";
            }else {
                // 评论
                BlogArticle article = blogArticleService.queryById(articleId);
                articleName = article.getTitle();
            }
        }else if (StrUtil.isNotBlank(ao.getComment())){
            // 回复
            blogComment.setReplyId(ao.getComment());
            // 根据回复的ID查询出回复的所有内容
            comment = blogCommentService.queryById(ao.getComment());
            articleId = comment.getArticle();
            articleName = comment.getArticleName();
        }else {
            return GraceJSONResult.error("数据有误");
        }

        blogComment.setArticle(articleId);
        blogComment.setArticleName(articleName);

        blogComment.setCreatedTime(now);
        blogComment.setUpdatedTime(now);

        Boolean aBoolean = blogCommentService.insertByBo(blogComment);

        // 增加评论数量
        blogArticleService.addCommentNumber(articleId);

        if (status == 0){
            return GraceJSONResult.error("此评论包含词汇需要人工审核");
        }
        if (aBoolean){
            // 构建当前评论的对象
            CommentVo vo = initComment(blogComment, user);
            if (comment == null){
                // 是留言或评论
                return GraceJSONResult.ok(vo);
            }else {
                // 是回复
                BlogUser user1 = blogUserService.queryById(comment.getUserId());
                CommentVo reVo = initComment(comment, user1);
                // 将此次评论内容放入回复列表
                List<CommentVo> reply = new ArrayList<>();
                reply.add(vo);
                reVo.setReply(reply);
                // 返回前端要的格式
                return GraceJSONResult.ok(reVo);
            }
        }else {
            return GraceJSONResult.error();
        }
    }

    @Override
    public TableDataInfo<CommentVo> getComment(PageQuery pageQuery, String articleId) {

        TableDataInfo<CommentVo> resultDate = new TableDataInfo<>();

        // 查询总条数
        // Long total = blogCommentService.queryCommentCount(articleId);
        // 分页查询数据
        if (StrUtil.isBlank(articleId)){
            resultDate.setTotal(0);
            resultDate.setRows(new ArrayList<>());
            return resultDate;
        }
        BlogComment bo = new BlogComment();
        bo.setArticle(articleId);
        bo.setStatus(Constant.AVAILABLE_TRUE);
        bo.setReplyId("null");
        TableDataInfo<BlogComment> tableDataInfo = blogCommentService.queryPageList(bo, pageQuery);

        // 设置总条数
        resultDate.setTotal(tableDataInfo.getTotal());

        // 构建结构返回
        List<CommentVo> list = new ArrayList<>();
        List<BlogComment> rows = tableDataInfo.getRows();
        for (BlogComment row : rows) {
            BlogUser user = blogUserService.queryById(row.getUserId());
            CommentVo commentVo = initComment(row, user);

            // 设置回复的评论
            BlogComment bo1 = new BlogComment();
            bo1.setReplyId(row.getId());
            bo1.setStatus(Constant.AVAILABLE_TRUE);
            List<BlogComment> childCommentList = blogCommentService.queryList(bo1);
            List<CommentVo> reply = new ArrayList<>();
            for (BlogComment blogComment : childCommentList) {
                BlogUser user1 = blogUserService.queryById(blogComment.getUserId());
                CommentVo vo = initComment(blogComment, user1);
                reply.add(vo);
            }
            commentVo.setReply(reply);
            list.add(commentVo);
        }

        // 设置集合
        resultDate.setRows(list);

        return resultDate;
    }

    @Override
    public List<RecentlyCommentVo> getBuzzUser() {
        // 查询评论最多的前三名
        List<RecentlyCommentVo> list = blogCommentService.getBuzzUser();
        for (RecentlyCommentVo vo : list) {
            BlogUser user = blogUserService.queryById(vo.getUserId());
            vo.setNickname(user.getNickname());
            vo.setHeadPortrait(user.getHeadPortrait());
        }
        return list;
    }

    @Override
    public List<RecentlyCommentVo> getRecentlyComment() {
        List<RecentlyCommentVo> list = new ArrayList<>();
        BlogComment bo = new BlogComment();
        bo.setStatus(Constant.AVAILABLE_TRUE);
        PageQuery pageQuery = new PageQuery();
        pageQuery.setLimit(3);
        bo.setReplyId("-1");
        TableDataInfo<BlogComment> tableDataInfo = blogCommentService.queryPageList(bo, pageQuery);
        List<BlogComment> rows = tableDataInfo.getRows();
        for (BlogComment row : rows) {
            RecentlyCommentVo vo = new RecentlyCommentVo();
            BlogUser user = blogUserService.queryById(row.getUserId());
            BeanUtil.copyProperties(row,vo);
            vo.setHeadPortrait(user.getHeadPortrait());
            vo.setNickname(user.getNickname());
            list.add(vo);
        }
        return list;
    }

    @Override
    public List<TimeLineVo> getGitCommitHistory() throws ParseException {
        List<TimeLineVo> list = new ArrayList<>();

        // 从缓存获取
        String commitHistory = redis.get(RedisKey.GIT_COMMIT_HISTORY);
        List<GitCommitHistoryVo> listHistory = new ArrayList<>();
        if (StrUtil.isNotBlank(commitHistory)){
            listHistory = JSONObject.parseArray(commitHistory, GitCommitHistoryVo.class);
            for (GitCommitHistoryVo historyVo : listHistory) {
                String date = historyVo.getDate();
                // 2022-01-01 11:11:11
                String year = date.substring(0,4);
                String month = date.substring(5,7);
                String day = date.substring(8,10);
                historyVo.setYear(year);
                historyVo.setMonth(month);
                historyVo.setDay(day);
            }
        }

        // 根据年分组
        List<String> years1 = listHistory.stream().map(GitCommitHistoryVo::getYear).collect(Collectors.toList());
        years1.sort((o1, o2) -> o2.compareTo(o1));
        LinkedHashSet<String> years = new LinkedHashSet<>(years1);
        Map<String, List<GitCommitHistoryVo>> yearMap = listHistory.stream()
                .collect(Collectors.groupingBy(GitCommitHistoryVo::getYear));

        for (String year : years) {
            TimeLineVo vo = new TimeLineVo();
            vo.setYear(year);
            List<GitCommitHistoryVo> yearList = yearMap.get(year);

            List<String> months1 = yearList.stream().map(GitCommitHistoryVo::getMonth).collect(Collectors.toList());
            months1.sort((o1, o2) -> o2.compareTo(o1));
            LinkedHashSet<String> months = new LinkedHashSet<>(months1);
            Map<String, List<GitCommitHistoryVo>> monthMap = yearList.stream()
                    .collect(Collectors.groupingBy(GitCommitHistoryVo::getMonth));
            LinkedHashMap<String, List<TimeLineVo.MonthData>> m =  new LinkedHashMap<>();
            for (String month : months) {
                List<GitCommitHistoryVo> gitCommitHistoryVos = monthMap.get(month);
                List<TimeLineVo.MonthData> dayList = new ArrayList<>();
                for (GitCommitHistoryVo gitCommitHistoryVo : gitCommitHistoryVos) {
                    dayList.add(new TimeLineVo.MonthData(gitCommitHistoryVo.getDate(),gitCommitHistoryVo.getMessage()));
                }
                m.put(month,dayList);
            }
            vo.setMonth(m);
            list.add(vo);
        }

        return list;
    }

    /**
     * 构建评论对象
     * @param blogComment       评论内容
     * @param user              评论人
     */
    private CommentVo initComment(BlogComment blogComment,BlogUser user){
        CommentVo vo = new CommentVo();
        BeanUtil.copyProperties(blogComment,vo);
        vo.setCommentId(blogComment.getId());
        CommentVo.CommentUser commentUser = new CommentVo.CommentUser();
        BeanUtil.copyProperties(user,commentUser);
        vo.setUser(commentUser);
        commentUser.setUserId(user.getId());
        return vo;
    }
}
